package com.example.mykotlinapp

import java.beans.PropertyChangeEvent
import java.beans.PropertyChangeListener
import java.beans.PropertyChangeSupport
import kotlin.properties.Delegates
import kotlin.reflect.KProperty


/**
 *
 *
 * @author zhudeshuai
 * @since 2019/7/17
 */

//委托属性
class Delegate {

    operator fun getValue(foo: Foo, property: KProperty<*>): Int {
        println("Delegate.getValue")
        return 2
    }

    operator fun setValue(foo: Foo, property: KProperty<*>, i: Int) {
        println("Delegate.setValue")
    }

}

class Foo {
    var p: Int by Delegate()
}

private fun test130() {
    val foo = Foo()
    println(foo.p)
    foo.p = 5
}

//惰性初始化和“by lazy()”

private class Person3 {
    val emails by lazy {
        //加载email
    }
}

//demo1：实现功能：当一个类的属性值发生改变时，收到通知
open class PropertyChangeAware {
    protected val changeSupport = PropertyChangeSupport(this)

    fun addPropertyChangeListener(listener: PropertyChangeListener) {
        changeSupport.addPropertyChangeListener(listener)
    }

    fun removePropertyChangeListener(listener: PropertyChangeListener) {
        changeSupport.removePropertyChangeListener(listener)
    }

}

val propertiChangeListener = PropertyChangeListener {
    println("property ${it.propertyName} changed from ${it.oldValue} to ${it.newValue}")
}

private class Person4(val name: String, age: Int) : PropertyChangeAware() {
    var age: Int = age
        set(value) {
            val oldAge = field
            field = value
            changeSupport.firePropertyChange("age", oldAge, value)
        }
}

private fun test131() {
    val person = Person4("Curry", 25)
    person.addPropertyChangeListener(PropertyChangeListener {
        println("property ${it.propertyName} changed from ${it.oldValue} to ${it.newValue}")
    })
    person.age = 30
}

//demo2:把demo1重复代码合并到委托类中
//属性委托类
class ObservableProperty(
    val propName: String,
    var propValue: Int,
    val changeSupport: PropertyChangeSupport
) {
    fun getValue(): Int = propValue
    fun setValue(value: Int) {
        val oldValue = propValue
        propValue = value
        changeSupport.firePropertyChange(propName, oldValue, value)
    }
}

private class Person5(val name: String, age: Int) : PropertyChangeAware() {
    val ageDelegate = ObservableProperty("age", age, changeSupport)
    var age: Int
        get() = ageDelegate.getValue()
        set(value: Int) = ageDelegate.setValue(value)
}

private fun test132() {
    val p = Person5("Curry", 30)
    p.addPropertyChangeListener(PropertyChangeListener {
        println("property ${it.propertyName} changed from ${it.oldValue} to ${it.newValue}")
    })
    p.age = 31
}

//demo3:继续优化委托类

class Person6(val name: String, age: Int) : PropertyChangeAware() {
    var age: Int by ObservablePropertyFinal(age, changeSupport)
}

//最终形态委托类
class ObservablePropertyFinal(
    var propValue: Int,
    val changeSupport: PropertyChangeSupport
) {
    operator fun getValue(p: Person6, prop: KProperty<*>): Int = propValue
    operator fun setValue(p: Person6, property: KProperty<*>, newValue: Int) {
        val oldValue = propValue
        propValue = newValue
        changeSupport.firePropertyChange(property.name, oldValue, newValue)
    }
}

private fun test133() {
    val p = Person6("Curry", 31)
    p.addPropertyChangeListener(PropertyChangeListener {
        println("property ${it.propertyName} changed from ${it.oldValue} to ${it.newValue}")
    })
    p.age = 32
    p.age = 28
}

//demo4:使用Delegates.observable 来实现
class Person7(val name: String, age: Int) : PropertyChangeAware() {
    private val observer = { prop: KProperty<*>, oldValue: Int, newValue: Int ->
        changeSupport.firePropertyChange(prop.name, oldValue, newValue)
    }

    var age: Int by Delegates.observable(age, observer)
}

private fun test134() {
    val p = Person7("Tom", 18)
    p.addPropertyChangeListener(propertiChangeListener)
    p.age = 20
}

private fun main() {
//    test134()
    val list = listOf(1,2,3,4)
    list.count {
        it == 3
    }
}